home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 22 code / Paper Juggling / Shell Files / ShellEvents.c < prev    next >
Encoding:
Text File  |  1995-04-18  |  19.4 KB  |  861 lines  |  [TEXT/MMCC]

  1. //---------------------------------------------------------------------
  2. //---------------------------------------------------------------------
  3. //
  4. //    Horrible Rickety Shell, by Dave Johnson
  5. //
  6. //    © Copyright 1985 - 1995 Anyone Who Wants It,
  7. //    All Rights Energetically Hurled as far away from me as possible.
  8. //    Use at your own (considerable) risk.
  9.  
  10.  
  11. #include    "PaperJuggling.h"
  12.  
  13. extern Boolean            gDoneFlag;
  14. extern Rect                gDeskRect;
  15. extern MenuHandle        gShellMenuHandles[];
  16. extern unsigned long    gClickTime, gSleepTime;
  17. extern short            gDocTitleHeight, gDocFrameWidth;     // Window Stats, for use in positioning
  18. extern ControlActionUPP    gScrollActionUPP;
  19.  
  20. /*-------------------------------------------------------------------------
  21. DoEvent()            Standard Event Handler...
  22. -------------------------------------------------------------------------*/
  23.  
  24. void DoEvent(EventRecord *Event)
  25. {
  26.     GrafPtr        oldport;
  27.     
  28.     // Allow app to handle raw event
  29.     if(AppDoEvent(Event) == true)
  30.         return;
  31.     
  32.     // Do standard event processing    
  33.     switch(Event->what)
  34.     {
  35.         case activateEvt:
  36.             DoActivate((WindowPtr)Event->message, Event->modifiers & activeFlag);
  37.             break;
  38.                 
  39.         case updateEvt:
  40.             {
  41.                 WindowPtr    wind = (WindowPtr)Event->message;
  42.                 
  43.                 if(IsAppWindow(wind))
  44.                 {
  45.                     GetPort(&oldport);
  46.                     SetPort(wind);
  47.                     ClipRect(&wind->portRect);
  48.                     BeginUpdate(wind);
  49.                     
  50.                     /* Draw the growbox and controls */    
  51.                     UpdateControls(wind, wind->visRgn);
  52.                     DrawGrowIcon(wind);
  53.                     
  54.                     // Call the app to draw content
  55.                     AppUpdate(wind);
  56.  
  57.                     EndUpdate(wind);
  58.                     SetPort(oldport);
  59.                 }
  60.             }
  61.             break;
  62.  
  63.         case mouseDown:
  64.             DoMouse(Event);
  65.             gClickTime = Event->when;
  66.             break;
  67.             
  68.         case keyDown:
  69.         case autoKey:
  70.             DoKey(Event);
  71.             break;
  72.         
  73.         case osEvt:
  74.             DoOS(Event);
  75.             break;
  76.         
  77.         case kHighLevelEvent:
  78.             DoHighLevel(Event);
  79.             break;
  80.         
  81.         case nullEvent:
  82.             AppIdle(Event);
  83.             break;
  84.     }
  85. }
  86.  
  87. void DoActivate(WindowPtr wind, Boolean activate)
  88. {
  89.     DocHandle        doc;
  90.     
  91.     if(!IsAppWindow(wind) || (doc = GetWindowDoc(wind)) == nil)
  92.         return;
  93.     
  94.     SetPort(wind);
  95.     if(activate)     // an activate event
  96.     {
  97.         
  98.         //  the growbox and controls must be redrawn on activation. 
  99.         DrawGrowIcon(wind);
  100.         ShowControl((*doc)->hScroll);
  101.         ShowControl((*doc)->vScroll);
  102.     }
  103.     else            // a deactivate event
  104.     {
  105.         //  the growbox and controls must be redrawn on de-activation, too. 
  106.         HideControl((*doc)->hScroll);
  107.         HideControl((*doc)->vScroll);
  108.         DrawGrowIcon(wind);
  109.     }
  110.     
  111.     // Notify app
  112.     AppActivate(wind, activate);
  113. }
  114.  
  115. /*------------------------------------------------------------------------
  116. DoMouse()            Handles mousedown events...
  117. -------------------------------------------------------------------------*/
  118.  
  119. void DoMouse(EventRecord *eventptr)
  120. {    
  121.     WindowPtr        whichWindptr;
  122.     Point            thePt;
  123.     long            mstuff;
  124.     short            part;
  125.     Boolean            doubleClick = false;
  126.  
  127.     
  128.     if((eventptr->when - gClickTime) <= GetDblTime())
  129.     {
  130.         doubleClick = true;
  131.     }
  132.     thePt = eventptr->where;
  133.     part = FindWindow(thePt, &whichWindptr);
  134.     switch(part)
  135.     {
  136.         case inDesk:
  137.             break;
  138.             
  139.         case inMenuBar:
  140.             DoAdjustMenus();
  141.             mstuff = MenuSelect(thePt);
  142.             DoMenus(mstuff);
  143.             break;
  144.             
  145.         case inSysWindow:
  146.             SystemClick(eventptr, whichWindptr);
  147.             break;
  148.         
  149.         case inContent:
  150.             if(whichWindptr != FrontWindow())
  151.                 SelectWindow(whichWindptr);
  152.             else
  153.             {
  154.                 SetPort(whichWindptr);
  155.                 GlobalToLocal(&thePt);
  156.                 DoContentClick(thePt, whichWindptr, doubleClick, eventptr);
  157.             }
  158.             break;
  159.             
  160.         case inDrag:
  161.             DragWindow(whichWindptr, thePt, &gDeskRect);
  162.             break;
  163.  
  164.         case inGrow:
  165.             DoGrowWindow(whichWindptr, thePt);
  166.             break;
  167.             
  168.         case inGoAway:
  169.             if(TrackGoAway(whichWindptr, thePt))
  170.             {
  171.                 DoClose(whichWindptr);
  172.                 DoAdjustMenus();
  173.             }
  174.             break;
  175.             
  176.         case inZoomIn:
  177.         case inZoomOut:
  178.             if(TrackBox(whichWindptr, thePt, part))
  179.                 DoZoomWindow(whichWindptr, part);
  180.             break;
  181.     }
  182. }
  183.  
  184. void DoAdjustMenus(void)
  185. {
  186.     MenuHandle    mhndl;
  187.     long        pictSize, ignored;
  188.     Boolean        windowsUp;
  189.             
  190.     /* OK, first the file menu. If the windows are up, then enable Close, Save (if
  191.         the window needs saving), and Save As. Also enable Page Setup, Print, and 
  192.         Print One. If there are no windows open, disable same. New, 
  193.         and Quit are always enabled. */
  194.     
  195.     windowsUp = (FrontWindow() != nil && IsAppWindow(FrontWindow()));
  196.     mhndl = gShellMenuHandles[kFileMenu];
  197.  
  198.     if(windowsUp)
  199.     {
  200.         DocHandle doc;
  201.         
  202.         EnableItem(mhndl, iClose);
  203.         doc = GetWindowDoc(FrontWindow());
  204.         if((*doc)->dirty)
  205.             EnableItem(mhndl, iSave);
  206.         else
  207.             DisableItem(mhndl, iSave);
  208.         EnableItem(mhndl, iSaveAs);
  209.         EnableItem(mhndl, iPageSetup);
  210.         EnableItem(mhndl, iPrint);
  211.         EnableItem(mhndl, iPrintOne);
  212.     }
  213.     else        //  The windows are closed 
  214.     {
  215.         DisableItem(mhndl, iClose);
  216.         DisableItem(mhndl, iSave);
  217.         DisableItem(mhndl, iSaveAs);
  218.         DisableItem(mhndl, iPageSetup);
  219.         DisableItem(mhndl, iPrint);
  220.         DisableItem(mhndl, iPrintOne);
  221.     }
  222.  
  223.     /* Now the Edit Menu. If the windows are up, enable Cut, Copy, and Clear 
  224.         automatically, and Undo and Paste conditionally. Otherwise, disable everything */
  225.         
  226.     mhndl = gShellMenuHandles[kEditMenu];
  227.     if(windowsUp)
  228.     {
  229.         EnableItem(mhndl, iCut);
  230.         EnableItem(mhndl, iCopy);
  231.         EnableItem(mhndl, iClear);
  232.         
  233.         //  For Paste: have to see if there is a PICT in the scrap 
  234.         pictSize = GetScrap(nil, 'PICT', &ignored);
  235.         if(pictSize > 0) //  We have a PICT in the scrap 
  236.             EnableItem(mhndl, iPaste);
  237.         else
  238.             DisableItem(mhndl, iPaste);
  239.         
  240.         //  Now Undo: 
  241.         DisableItem(mhndl, iUndo);
  242.     }
  243.     else
  244.     {
  245.         DisableItem(mhndl, iUndo);
  246.         DisableItem(mhndl, iCut);
  247.         DisableItem(mhndl, iCopy);
  248.         DisableItem(mhndl, iPaste);
  249.         DisableItem(mhndl, iClear);
  250.     }
  251.     
  252.     // Now the App
  253.     AppAdjustMenus();
  254. }    
  255.  
  256.  
  257. // Handle scrollbars
  258. void DoContentClick(Point thePt, WindowPtr wind, Boolean doubleClick, EventRecord *eventptr)
  259. {
  260.     Point                lastPoint = {0, 0};
  261.     short                part, value;
  262.     ControlHandle        control;
  263.     DocHandle            doc;
  264.  
  265.     doc = GetWindowDoc(wind);
  266.     if(doc == nil)
  267.         return;
  268.                     
  269.     //  Look for a click in a scrollbar: if so deal with it 
  270.     part = FindControl(thePt, wind, &control);
  271.     if(part != 0)
  272.     {
  273.         switch ( part )
  274.         {
  275.             //  The thumb is special, and doesn't use the Action Proc 
  276.             case inThumb: 
  277.                 value = GetCtlValue(control);
  278.                 part = TrackControl(control, thePt, nil);
  279.                 if ( part != 0 ) //  Good thumb drag 
  280.                 { 
  281.                     value -= GetCtlValue(control);
  282.                     //  value now has CHANGE in value; if value changed, scroll 
  283.                     if ( value != 0 )
  284.                         if ( control == (*doc)->hScroll )
  285.                             DoScroll(wind, value, 0, true);
  286.                         else
  287.                             DoScroll(wind, 0, value, true);
  288.                 }
  289.                 break;
  290.                 
  291.             default:    //  they clicked in an arrow, so track & scroll 
  292.                 value = TrackControl(control, thePt, gScrollActionUPP);
  293.                 break;
  294.         }
  295.     }
  296.     else
  297.         AppClick(thePt, wind, doubleClick, eventptr);
  298. }
  299.  
  300. // Grow the window, adjusting scroll bars and such, then inform the App what happened
  301. void DoGrowWindow(WindowPtr wind, Point where)
  302. {
  303.     Rect            limits;
  304.     long            size;
  305.     DocHandle        doc;
  306.     
  307.     doc = GetWindowDoc(wind);
  308.     if(doc == nil)
  309.         return;
  310.             
  311.     //  Do nothing if not our window 
  312.     if(IsAppWindow(wind) == false)
  313.         return;
  314.         
  315.     //  Set up size limits 
  316.     limits.top = limits.left = kMinWindowSize; //  One inch minimum 
  317.     /* These are actually bigger than the maximum size of the portRect, 
  318.     since the outline dragged by GrowWindow is the outline of the window frame,
  319.     not its portRect */
  320.     limits.right = (*doc)->contentSize.h + kScrollAdjust + gDocFrameWidth;
  321.     limits.bottom = (*doc)->contentSize.v + kScrollAdjust + gDocFrameWidth;
  322.     
  323.     //  Let the user grow the window 
  324.     size = GrowWindow(wind, where, &limits);
  325.     
  326.     /* If the size changed, then erase the scrollbars and grow box area and size the 
  327.     window, adjusting the scroll bars and so on */
  328.     if(size != 0)
  329.     {
  330.         Rect    tempRect;
  331.         short    hSize, vSize;
  332.         
  333.         SetPort(wind);
  334.         
  335.         //  Should erase the scrollbars and grow box area before resizing the window: 
  336.         //  make a rect for the growBox 
  337.         tempRect = wind->portRect;
  338.         tempRect.top = tempRect.bottom - kScrollAdjust;
  339.         tempRect.left = tempRect.right - kScrollAdjust;
  340.         
  341.         //  Erase it and the scroll bars 
  342.         EraseRect(&tempRect);
  343.         InvalRect(&tempRect); // add to update region
  344.         HideControl((*doc)->hScroll);
  345.         HideControl((*doc)->vScroll);
  346.         
  347.         /* OK, size it, but first make sure that the size is within limits (users
  348.         can hold down the command key to bypass the limit, but we won't let 'em). 
  349.         Note that we subtract from the limits to account for the window frame */
  350.         hSize = LoWord(size);
  351.         vSize = HiWord(size);
  352.         if(hSize > limits.right - gDocFrameWidth) hSize = limits.right - gDocFrameWidth;
  353.         if(vSize > limits.bottom - gDocFrameWidth) vSize = limits.bottom - gDocFrameWidth;
  354.         SizeWindow(wind, hSize, vSize, true);
  355.         ClipRect(&wind->portRect);
  356.         
  357.         // Reset gx clip 
  358.         ResetGXClip(wind);
  359.  
  360.         //  adjust scrollBars 
  361.         AdjustScrollbars(wind, true);
  362.         
  363.         //  re-show controls and grow icon if in the front 
  364.         if(FrontWindow() == wind)
  365.         {
  366.             ShowControl((*doc)->hScroll);
  367.             ShowControl((*doc)->vScroll);
  368.             DrawGrowIcon(wind);
  369.         }
  370.             
  371.         // Tell application about it
  372.         AppGrowWindow(wind, hSize, vSize);
  373.     }
  374. }
  375.  
  376. void DoZoomWindow(WindowPtr wind, short zoomDir)
  377. {
  378.     Rect            worldRect = {0, 0, 0, 0};
  379.     DocHandle        doc;
  380.     
  381.     //  Do nothing if not our window 
  382.     doc = GetWindowDoc(wind);
  383.     if(doc == nil)
  384.         return;
  385.             
  386.     //  Get the maximum size of the window, and set up the window for the zoom 
  387.     worldRect.right =  (*doc)->contentSize.h; //  top left is always 0, 0 
  388.     worldRect.bottom =  (*doc)->contentSize.v;
  389.     ReadyWZoom(wind, zoomDir, worldRect.right + kScrollAdjust, worldRect.bottom + kScrollAdjust);
  390.     
  391.     /* Ok, zoom that sucker. Erase the window completely first: cosmetically this looks
  392.         good */
  393.     SetPort(wind);
  394.     EraseRect(&wind->portRect);
  395.     ZoomWindow(wind, zoomDir, true);
  396.     ClipRect(&wind->portRect);
  397.  
  398.     // Reset gx clip 
  399.     ResetGXClip(wind);
  400.  
  401.     // If window is in fromt, reset scroll bars, etc, hiding them first
  402.     // to avoid unnecessary drawing.
  403.     if(FrontWindow() == wind)
  404.     {
  405.         HideControl((*doc)->hScroll);
  406.         HideControl((*doc)->vScroll);
  407.         AdjustScrollbars(wind, true);
  408.         ShowControl((*doc)->hScroll);
  409.         ShowControl((*doc)->vScroll);
  410.         DrawGrowIcon(wind);
  411.     }
  412.  
  413.     // Tell the App what happened
  414.     AppZoomWindow(wind, zoomDir);
  415. }
  416.  
  417. /*-----------------------------------------------------------------------
  418. DoKey()            Handles keypresses...
  419. ------------------------------------------------------------------------*/
  420.  
  421. void DoKey(EventRecord *eventptr)
  422. {
  423.     char    key;
  424.     
  425.     key = (char)(eventptr->message);
  426.     if(eventptr->modifiers & cmdKey)
  427.     {
  428.         AppAdjustMenus();
  429.         DoMenus(MenuKey(key));
  430.     }
  431. }
  432.     
  433. /*-----------------------------------------------------------------------
  434. DoOS()    Handles suspend and resume events, ignores mouse moved events
  435. ------------------------------------------------------------------------*/
  436.  
  437. void DoOS(EventRecord *eventPtr)
  438. {
  439.     // Get the high byte of the message.
  440.     switch ((eventPtr->message >> 24) & 0x0FF)
  441.     {
  442.         case suspendResumeMessage:
  443.             {
  444.                 Boolean        resuming = eventPtr->message & resumeFlag;
  445.                 WindowPtr    window;
  446.     
  447.                 if(resuming)            // if resume event
  448.                 {                                            // we're switching back from another app so..
  449.                     gSleepTime = 0;                                // speed up  
  450.     
  451.                     // On a resume event, we need to call GXUpdateJob on all of our
  452.                     // documents' jobs.  This is important because the user may have
  453.                     // just changed something which affects our jobs (like the size
  454.                     // of the paper in the printer).
  455.                     //
  456.                     // Since our application stores our document references in the refCon fields
  457.                     // of our documents' windows, we just loop through every one of our windows,
  458.                     // extract our document pointers and update the associated jobs.
  459.         
  460.                     window = FrontWindow();
  461.                     while (window != nil)
  462.                     {
  463.                         if ( IsAppWindow(window) )
  464.                             GXUpdateJob(GetWindowGXJob(window));
  465.                         window = (WindowPtr) ((WindowPeek) window)->nextWindow;
  466.                     }
  467.                 }
  468.                 else                            // if suspend event
  469.                     gSleepTime=80;                    // we're switching to another app so slow down...
  470.                 
  471.                 // Since I set the doesActivateOnFGSwitch flag in the SIZE resource, I need to
  472.                 // activate the front window too.
  473.                 DoActivate(FrontWindow(), resuming);
  474.             }
  475.             break;
  476.  
  477.         case mouseMovedMessage:
  478.             break;
  479.     }
  480. }
  481.     
  482.  
  483. /*-----------------------------------------------------------------------
  484. DoHighLevel()    Handles  high level events (including Apple Events)
  485. ------------------------------------------------------------------------*/
  486.  
  487. void DoHighLevel(EventRecord *eventPtr)
  488. {
  489.     OSErr        err;
  490.     
  491.     // Assume it's an Apple Event, since we don't define any others
  492.     err = AEProcessAppleEvent(eventPtr);
  493.     if(err != noErr)
  494.         SysBeep(10);
  495. }
  496.     
  497.  
  498. /*-----------------------------------------------------------------------
  499. DoMenus()            Handles a menu selection...
  500. ------------------------------------------------------------------------*/
  501.  
  502. void DoMenus(long mstuff)
  503. {
  504.     short            id, item;
  505.     
  506.     if(HiWord(mstuff) == 0)
  507.         return;
  508.  
  509.     id = HiWord(mstuff);
  510.     item = LoWord(mstuff);
  511.     switch(id)
  512.     {
  513.         case kAppleMenuID:
  514.             DoApple(item);
  515.             break;
  516.             
  517.         case kFileMenuID:
  518.             DoFile(item);
  519.             break;
  520.  
  521.         case kEditMenuID:
  522.             DoEdit(item);
  523.             break;
  524.  
  525.         default:
  526.             AppMenu(id, item);
  527.             break;
  528.     }
  529.     HiliteMenu(0);
  530. }
  531.  
  532. /*-----------------------------------------------------------------------
  533. DoApple()            Handles apple menu...
  534. ------------------------------------------------------------------------*/
  535.  
  536. void DoApple(short item)
  537. {
  538.     Str255                name;
  539.  
  540.     switch(item)
  541.     {
  542.         case iAbout:
  543.             Alert(kAboutAlertID, nil);
  544.             break;
  545.         
  546.         default:
  547.             GetItem(gShellMenuHandles[kAppleMenu], item, name);
  548.             OpenDeskAcc(name);
  549.     }
  550. }
  551.             
  552. /*-----------------------------------------------------------------------
  553. DoFile()            Handles File menu...
  554. ------------------------------------------------------------------------*/
  555.     
  556. void DoFile(short item)
  557. {
  558.     WindowPtr    wind = FrontWindow();
  559.     
  560.     switch(item)
  561.     {
  562.         case iNew:        //  New... 
  563.             AppNew(0, 0);
  564.             break;
  565.                         
  566.         case iOpen:   //  Open...  
  567.             AppOpen();
  568.             break;
  569.  
  570.         case iClose:   //  Close...  
  571.             DoClose(wind);
  572.             break;
  573.  
  574.         case iSave:  //  Save... 
  575.             AppSave(wind);
  576.             break;
  577.             
  578.         case iSaveAs:  //  Save As... 
  579.             AppSaveAs(wind);
  580.             break;
  581.             
  582.         case iPageSetup:  //  Page Setup... 
  583.             AppPageSetup(wind);
  584.             break;
  585.             
  586.         case iPrint:  //  Print... 
  587.             AppPrint(wind);
  588.             break;
  589.             
  590.         case iPrintOne:  //  Print... 
  591.             AppPrintOne(wind);
  592.             break;
  593.             
  594.         case iQuit:  //  Quit 
  595.             // If the user cancels any saves CloseAllDocs returns false, otherwise it returns true
  596.             gDoneFlag = CloseAllDocs();
  597.             break;
  598.     }
  599.     DoAdjustMenus(); // Keep Menus up to date
  600. }
  601.  
  602. /*-----------------------------------------------------------------------
  603. void DoEdit()            Handles Edit menu...
  604. ------------------------------------------------------------------------*/
  605.     
  606. void DoEdit(short item)
  607. {
  608.     /* First call SystemEdit to let a DA do editing, if one is frontmost. We
  609.         pass it the item - 1 since the constants for the edit commands are zero-based */
  610.     if(SystemEdit(item - 1) == false)
  611.     {
  612.         //  The command is for the app since SystemEdit didn't handle it. 
  613.         switch(item)
  614.         {
  615.             case iUndo:
  616.                 AppUndo();
  617.                 break;
  618.     
  619.             case iCut:
  620.                 AppCut();
  621.                 break;
  622.                 
  623.             case iCopy:
  624.                 AppCopy();
  625.                 break;
  626.     
  627.             case iPaste:
  628.                 AppPaste();
  629.                 break;
  630.     
  631.             case iClear:
  632.                 AppClear();
  633.                 break;
  634.         }
  635.     }
  636. }
  637.  
  638. // 
  639. Boolean DoClose(WindowPtr wind)
  640. {
  641.     Boolean            closeIt = true;
  642.     DocHandle doc;
  643.     
  644.     doc = GetWindowDoc(wind);
  645.     if(doc != nil)
  646.     {
  647.         //  If it needs saving, do the dialog 
  648.         if((*doc)->dirty)
  649.         {
  650.             short        rslt;
  651.             
  652.             rslt = SaveChangesDlog();
  653.             switch(rslt)
  654.             {
  655.                 case 1:    //  Save 
  656.                     closeIt = AppSave(wind); /*    AppSave() returns true only if the save
  657.                                                 completed successfuly (user didn't cancel,
  658.                                                 no errors */
  659.                     break;
  660.                 
  661.                 case 4:    // No save
  662.                     break; // closeIt already true.
  663.                 
  664.                 case 2:    //  Cancel 
  665.                     closeIt = false;
  666.                     break;
  667.             }
  668.         }
  669.     
  670.         // Kill the window, if indicated
  671.         if(closeIt)
  672.         {
  673.             AppClose(wind);
  674.         }
  675.     }
  676.     return closeIt;
  677. }
  678.  
  679. /* Apple Event handlers */
  680. pascal OSErr OAPPHandler(AppleEvent *theAEvent, AppleEvent *reply, long refcon)
  681. {
  682.     OSErr    err;
  683.     
  684.     err = MyGotRequiredParams(theAEvent);
  685.     if (err)
  686.         return err;
  687.     else {
  688.         // Do anything that should happen on an Open.
  689.         CursHandle    curs;
  690.  
  691.         // Set cursor to watch
  692.         curs = GetCursor(watchCursor);
  693.         SetCursor(*curs);
  694.         
  695.         // Make a new document
  696.         // AppNew(0, 0);
  697.         
  698.         // Set cursor to arrow
  699.         SetCursor(&qd.arrow);
  700.         
  701.         return noErr;
  702.     }
  703. }
  704.  
  705. pascal OSErr ODOCHandler(AppleEvent *theAEvent, AppleEvent *reply, long refcon)
  706. {
  707.     FSSpec        myFSS;
  708.     AEDescList    docList;
  709.     OSErr        err;
  710.     long        index, itemsInList;
  711.     Size        actualSize;
  712.     AEKeyword    keywd;
  713.     DescType    returnedType;
  714.  
  715.     // get the direct parameter--a descriptor list--and put
  716.     // it into docList
  717.     err = AEGetParamDesc(theAEvent, keyDirectObject,
  718.                             typeAEList, &docList);
  719.     if (err)
  720.         return err;
  721.  
  722.     // check for missing required parameters
  723.     err = MyGotRequiredParams(theAEvent);
  724.     if (err) {
  725.         // an error occurred:  do the necessary error handling
  726.         err = AEDisposeDesc(&docList);
  727.         return    err;
  728.     }
  729.     
  730.     // count the number of descriptor records in the list
  731.     err = AECountItems (&docList, &itemsInList);
  732.  
  733.     // now get each descriptor record from the list, coerce
  734.     // the returned data to an FSSpec record, and open the
  735.     // associated file
  736.     for (index = 1; index <= itemsInList; index++)
  737.     {
  738.         err = AEGetNthPtr(&docList, index, typeFSS, &keywd,
  739.                             &returnedType, (Ptr)&myFSS,
  740.                             sizeof(myFSS), &actualSize);
  741.         if (err)
  742.             SysBeep(10);
  743.         
  744.         // Open the file
  745.         err = OpenJuggleFile(&myFSS, nil);
  746.         
  747.         if (err)
  748.             SysBeep(10);
  749.     }
  750.  
  751.     err = AEDisposeDesc(&docList);
  752.     DoAdjustMenus();
  753.     return    noErr;
  754. }
  755.  
  756. pascal OSErr PDOCHandler(AppleEvent *theAEvent, AppleEvent *reply, long refcon)
  757. {
  758.     FSSpec        myFSS;
  759.     AEDescList    docList;
  760.     OSErr        err;
  761.     long        index, itemsInList;
  762.     Size        actualSize;
  763.     AEKeyword    keywd;
  764.     DescType    returnedType;
  765.     WindowPtr    wind;
  766.  
  767.     // get the direct parameter--a descriptor list--and put
  768.     // it into docList
  769.     err = AEGetParamDesc(theAEvent, keyDirectObject,
  770.                             typeAEList, &docList);
  771.     if (err)
  772.         return err;
  773.  
  774.     // check for missing required parameters
  775.     err = MyGotRequiredParams(theAEvent);
  776.     if (err) {
  777.         // an error occurred:  do the necessary error handling
  778.         err = AEDisposeDesc(&docList);
  779.         return    err;
  780.     }
  781.  
  782.     // count the number of descriptor records in the list
  783.     err = AECountItems (&docList, &itemsInList);
  784.  
  785.     // now get each descriptor record from the list, coerce
  786.     // the returned data to an FSSpec record, and open the
  787.     // associated file
  788.     for (index = 1; index <= itemsInList; index++)
  789.     {
  790.         err = AEGetNthPtr(&docList, index, typeFSS, &keywd,
  791.                             &returnedType, (Ptr)&myFSS,
  792.                             sizeof(myFSS), &actualSize);
  793.         if (err)
  794.             SysBeep(10);
  795.         
  796.         // Open the file, making a new window
  797.         err = OpenJuggleFile(&myFSS, &wind);
  798.         if(err == noErr)
  799.         {
  800.             err = AppPrintOne(wind);
  801.             DoClose(wind);
  802.         }
  803.         
  804.         if (err)
  805.             SysBeep(10);
  806.     }
  807.  
  808.     err = AEDisposeDesc(&docList);
  809.     return    noErr;
  810. }
  811.  
  812. pascal OSErr QUITHandler(AppleEvent *theAEvent, AppleEvent *reply, long refcon)
  813. {
  814.     OSErr    err;
  815.  
  816.     // check for missing required parameters
  817.     err = MyGotRequiredParams(theAEvent);
  818.     if (err) {
  819.         // an error occurred:  do the necessary error handling
  820.         return    err;
  821.     }
  822.     
  823.     // Set the global flag if the user doesn't cancel
  824.     gDoneFlag = CloseAllDocs();
  825.     if(gDoneFlag == false)
  826.         return    userCanceledErr;
  827.     else
  828.         return    noErr;
  829. }
  830.  
  831. OSErr    MyGotRequiredParams (AppleEvent *theAEvent)
  832. {
  833.     DescType    returnedType;
  834.     Size        actualSize;
  835.     OSErr        err;
  836.  
  837.     err = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
  838.                     typeWildCard, &returnedType,
  839.                     nil, 0, &actualSize);
  840.  
  841.     if (err == errAEDescNotFound)    // you got 'em all
  842.         return    noErr;
  843.     else
  844.         if (err == noErr)  // you missed a required parameter
  845.             return    errAEParamMissed;
  846.         else    // the call to AEGetAttributePtr failed
  847.             return    err;
  848. }
  849.  
  850.  
  851. /*---------------------------------
  852. void BailOut()        Clean up and split...
  853. ----------------------------------- */
  854.  
  855. void BailOut(void)
  856. {
  857.     AppCleanUp();
  858.     ExitToShell();
  859. }
  860.  
  861.